//
// Name: genVBinc.js
// Copyright: Microsoft 2008
// Revision: 1.01
//
// This script can be used to generate a Visual Basic .vb file that contains
// the equivalent WPD property-keys and GUIDs as defined in
// portabledevice.h
// This script is provided as-is and Microsoft does not assume any
// liability. This script may be redistributed as long as the file
// contains these terms of use unmodified.
//
// Usage:
// Switch to the folder where portabledevice.h is present and then run
//     cscript //nologo genVBinc.js
// This will generate portabledeviceconstants.vb. This .vb file can
// then be included in a Visual Basic .Net project. 
// To use the propertykeys and the GUIDs, add "using PortableDeviceConstants"
// to the target file.
// Propertykeys can then be referenced as PortableDevicePKeys.desired_prop_name
//     e.g. PortableDevicePKeys.WPD_PROPERTY_COMMON_HRESULT
// GUIDs can be referenced as PortableDeviceGuids.desired_GUID_name
//     e.g. PortableDeviceGuids.WPD_OBJECT_FORMAT_ALL
//

//
// Use FSO to read/write input/output
//
var fso = new ActiveXObject("Scripting.FileSystemObject");

var f = null;
var fOut = null;
var sIn = "portabledevice.h";
var sOut = "portabledeviceconstants.vb";

// Added below to handle conversion of hexadecimal GUID string into its
// decimal equivalent.
var strGuidHex = null;


//
// Check for input file
//
try
{
    f = fso.OpenTextFile(sIn);
}
catch(e)
{
    WScript.Echo("Expected portabledevice.h to be in the current folder!");
}

//
// Check for output file
//
try
{
    fOut = fso.OpenTextFile(sOut, 2, true);
}
catch(e)
{
    WScript.Echo("Cannot open " + sOut + " for writing!");
}

//
// Write out header
//
fOut.Write("\
Imports System\r\n\
\r\n\
Namespace PortableDeviceConstants\r\n\
\r\n\
    Public Class PortableDevicePKeys\r\n\
    \r\n\
        Shared Sub New()\r\n\
        \r\n\
");    

//
// RegEx declarations for PKEYs and GUIDs
//
//e.g. DEFINE_PROPERTYKEY( WPD_CLIENT_MINOR_VERSION , 0x204D9F0C, 0x2292, 0x4080, 0x9F, 0x42, 0x40, 0x66, 0x4E, 0x70, 0xF8, 0x59 , 4 ); 
var rePKEY = /\s*DEFINE_PROPERTYKEY\(\s*(\w+)\s*,\s*(.+)\s*,\s*(\d+)\s*\);/;
var arrPKEY = new Array();

//e.g. DEFINE_GUID(WPD_EVENT_DEVICE_RESET, 0x7755CF53, 0xC1ED, 0x44F3, 0xB5, 0xA2, 0x45, 0x1E, 0x2C, 0x37, 0x6B, 0x27 ); 
var reGUID = /\s*DEFINE_GUID\((\w+),\s(.+)\s\);/;
var arrGUID = new Array();

//
// Parse the file
//
while (!f.AtEndOfStream)
{
    var l = f.ReadLine();
    var pattern = /0x/g;
    var replacement = "0x";

    //
    // Check for PKEYs
    //
    if (l.match(rePKEY))
    {
        //
        // Write out initializations for the PKEYs
        //
        var sName = l.replace(rePKEY, "$1");
        var sGUID = l.replace(rePKEY, "$2");
	    strGuidHex = sGUID.replace(pattern, replacement, 11);
        var sPID = l.replace(rePKEY, "$3");

        strGuidDec = convertHexGuid(strGuidHex)

        fOut.Write("            " + sName + ".fmtid = New Guid( " + strGuidDec + ")\r\n");
        fOut.Write("            " + sName + ".pid = " + sPID + "\r\n");
        fOut.Write("\r\n");

        //
        // Save the PKEY name for declaration at class level
        //
        arrPKEY.push(sName);
    }
    else if (l.match(reGUID))
    {
        //
        // Save the GUIDs since they go into a second class
        //
        var sName = l.replace(reGUID, "$1");
        var sGUID = l.replace(reGUID, "$2");
	    var sGUIDNew = sGUID.replace(pattern, replacement, 11);
        
        strGuidDec = convertHexGuid(sGUIDNew);
        arrGUID.push("Public Shared " + sName + " As New Guid( " + strGuidDec + " )");
    }
}

//
// Write out declarations for PKEYs
//
fOut.Write("        End Sub\r\n\r\n");

for (var i = 0; i < arrPKEY.length; i++)
{
    fOut.Write("        " + "Public Shared " + arrPKEY[i] + "As PortableDeviceApiLib._tagpropertykey\r\n");
}

fOut.Write("\
    End Class' class PortableDevicePKeys\r\n\
");

//
// Write out GUIDs
//
fOut.Write("\r\n\r\n");
fOut.Write("\
    Public Class PortableDeviceGuids\r\n\
    \r\n\
");

for (var i = 0; i < arrGUID.length; i++)
{
    fOut.Write("        " + arrGUID[i] + "\r\n");
}

//
// Write out footer
//
fOut.Write("\
    End Class' class PortableDeviceGuids\r\n\
End Namespace' namespace PortableDeviceConstants\r\n\
");

WScript.Echo("Done: " + sOut + " now contains VB WPD constants");

//
// Converts a hexadecimal GUID of the form: "( 0x204D9F0C, 0x2292, 0x4080, 0x9F, 0x42, 0x40, 0x66, 0x4E, 0x70, 0xF8)"
// into a decimal GUID.
//
function convertHexGuid(strGuidHex)
{
    var strArray = null;
    var strHexVal = null;
    var strDecVal = null;
    var strGuidDec = null;
    var i = null;
    
    // Split the hexadecimal GUID into its parts
    strArray = strGuidHex.split(",");
    for (i=0; i<strArray.length; i++)
    {
        // Remove the opening or closing parenthesis "(" or ")" in the
        // GUID string.
        if (strArray[i].indexOf("(") != -1)
            strHexVal = strArray[i].replace("(", "");
        else if (strArray[i].indexOf(")") != -1)
            strHexVal = strArray[i].replace(")", "");
        else
            strHexVal = strArray[i];
        
        // Convert each value within the GUID string to decimal.
        strDecVal = parseInt(strHexVal);
    
        // Concatenate the decimal equivalent value into the new GUID string
        strGuidDec += strDecVal;
        if (i<(strArray.length-1))
            strGuidDec += ", ";
    }
    return strGuidDec;
}
